import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class ThemeProvider with ChangeNotifier {
  // 字体列表
  static const fontList = ['system', 'kuaile'];
  // 当前字体索引
  late int _fontIndex = 0;

  // 当前主题颜色
  late MaterialColor _themeColor;
  late MaterialColor _initThemeColor;
  // 用户选择的明暗模式
  late bool _userThemeMode;
  // 用户亮度设置(0-255,透明到全黑)
  int _lightNumber = 0;

  BlendMode _blendMode = BlendMode.darken;
  late ThemeData _themeData;

  // 构造ThemeProvider
  ThemeProvider({int? primary, Map<int, Color>? swatch}) {
    _userThemeMode = false;
    int primaryColor = primary ?? 0xFF3F51B5;
    _initThemeColor = MaterialColor(
      primaryColor,
      swatch ??
          <int, Color>{
            50: const Color(0xFFE8EAF6),
            100: const Color(0xFFC5CAE9),
            200: const Color(0xFF9FA8DA),
            300: const Color(0xFF7986CB),
            400: const Color(0xFF5C6BC0),
            500: Color(primaryColor),
            600: const Color(0xFF3949AB),
            700: const Color(0xFF303F9F),
            800: const Color(0xFF283593),
            900: const Color(0xFF1A237E),
          },
    );
    _themeColor = _initThemeColor;
  }

  MaterialColor get initPrimaryColor => _initThemeColor;
  MaterialColor get primaryColor => _themeColor;
  int get lightNumber => _lightNumber;
  BlendMode get blendMode => _blendMode;
  ThemeData get theme => _themeData;

  // 切换字体
  void switchFont(int index) {
    _fontIndex = index;
    notifyListeners();
  }

  // 设置系统亮度
  void setLightNumber(int number) {
    _lightNumber = number;
    notifyListeners();
  }

  void switchTheme({bool? userThemeMode, MaterialColor? color}) {
    _userThemeMode = userThemeMode ?? _userThemeMode;
    _themeColor = color ?? _themeColor;
    notifyListeners();
  }

  void switchBlendMode(BlendMode? blend) {
    _blendMode = blend ?? BlendMode.darken;
    notifyListeners();
  }

  // 根据主题 明暗和颜色 生成对应的主题
  ThemeData themeData({bool isPlatformTheme = false}) {
    bool isDarkMode = isPlatformTheme || _userThemeMode;
    Brightness brightness = isDarkMode ? Brightness.dark : Brightness.light;
    var accentColor = isDarkMode ? _themeColor : _themeColor[500];
    _themeData = ThemeData(
      // 1.亮度
      brightness: brightness,
      // 2.primarySwatch传入不是Color, 而是MaterialColor(包含了primaryColor和accentColor)
      primarySwatch: _themeColor,
      // 主题颜色属于亮色系还是属于暗色系(eg:dark时,AppBarTitle文字及状态栏文字的颜色为白色,反之为黑色)
      // 这里设置为dark目的是,不管App是明or暗,都将appBar的字体颜色的默认值设为白色.
      // 再AnnotatedRegion<SystemUiOverlayStyle>的方式,调整响应的状态栏颜色
      // 3.primaryColor: 单独设置导航和TabBar的颜色
      primaryColor: _themeColor,
      // // 5.Button的主题
      // buttonTheme: ButtonThemeData(),
      // 6.Card的主题
      // cardTheme: const CardTheme(),
      // // 7.Text的主题
      textTheme: TextTheme(
          displayLarge: TextStyle(
              fontSize: 24.0, fontWeight: FontWeight.bold, color: _themeColor),
          displayMedium:
              const TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
          bodyLarge: TextStyle(color: _themeColor)),
      fontFamily: fontList[_fontIndex],
      appBarTheme: AppBarTheme(backgroundColor: _themeColor),
    );

    _themeData = _themeData.copyWith(
      brightness: brightness,
      cupertinoOverrideTheme: CupertinoThemeData(
        primaryColor: _themeColor,
        brightness: brightness,
      ),
      appBarTheme: _themeData.appBarTheme.copyWith(elevation: 0),
      splashColor: Colors.transparent,
      highlightColor: Colors.transparent,
      hintColor: _themeData.hintColor.withAlpha(90),

      /// 解决中文hint不居中的问题 https://github.com/flutter/flutter/issues/40248
      textTheme: _themeData.textTheme.copyWith(),
      chipTheme: _themeData.chipTheme.copyWith(
        pressElevation: 0,
        padding: const EdgeInsets.symmetric(horizontal: 10),
        labelStyle: _themeData.textTheme.bodySmall,
        backgroundColor: _themeData.chipTheme.backgroundColor?.withOpacity(0.1),
      ),
      inputDecorationTheme: ThemeHelper.inputDecorationTheme(_themeData),
      switchTheme: SwitchThemeData(
        thumbColor: MaterialStateProperty.resolveWith<Color?>(
            (Set<MaterialState> states) {
          if (states.contains(MaterialState.disabled)) {
            return null;
          }
          if (states.contains(MaterialState.selected)) {
            return accentColor;
          }
          return null;
        }),
        trackColor: MaterialStateProperty.resolveWith<Color?>(
            (Set<MaterialState> states) {
          if (states.contains(MaterialState.disabled)) {
            return null;
          }
          if (states.contains(MaterialState.selected)) {
            return accentColor;
          }
          return null;
        }),
      ),
      radioTheme: RadioThemeData(
        fillColor: MaterialStateProperty.resolveWith<Color?>(
            (Set<MaterialState> states) {
          if (states.contains(MaterialState.disabled)) {
            return null;
          }
          if (states.contains(MaterialState.selected)) {
            return accentColor;
          }
          return null;
        }),
      ),
      checkboxTheme: CheckboxThemeData(
        fillColor: MaterialStateProperty.resolveWith<Color?>(
            (Set<MaterialState> states) {
          if (states.contains(MaterialState.disabled)) {
            return null;
          }
          if (states.contains(MaterialState.selected)) {
            return accentColor;
          }
          return null;
        }),
      ),
    );
    return _themeData;
  }
}

class ThemeHelper {
  static InputDecorationTheme inputDecorationTheme(ThemeData theme) {
    Color primaryColor = theme.primaryColor;
    Color dividerColor = theme.dividerColor;
    Color errorColor = theme.colorScheme.error;
    Color disabledColor = theme.disabledColor;
    double width = 0.5;

    return InputDecorationTheme(
      hintStyle: const TextStyle(fontSize: 14),
      errorBorder: UnderlineInputBorder(
          borderSide: BorderSide(width: width, color: errorColor)),
      focusedErrorBorder: UnderlineInputBorder(
          borderSide: BorderSide(width: 0.7, color: errorColor)),
      focusedBorder: UnderlineInputBorder(
          borderSide: BorderSide(width: width, color: primaryColor)),
      enabledBorder: UnderlineInputBorder(
          borderSide: BorderSide(width: width, color: dividerColor)),
      border: UnderlineInputBorder(
          borderSide: BorderSide(width: width, color: dividerColor)),
      disabledBorder: UnderlineInputBorder(
          borderSide: BorderSide(width: width, color: disabledColor)),
    );
  }
}
